#include <linux/module.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/msi.h>
#include <linux/mutex.h>
#define EN_CDEV     // 使能 字符设备
#ifdef EN_CDEV
#include <linux/cdev.h>
#endif // EN_CDEV
#define EN_IRQ      // 使能 IRQ
#ifdef EN_IRQ
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#endif  // EN_IRQ
#define EN_CANFD    // 使能 CANFD IP
#if (defined(EN_CAN) || defined(EN_CANFD))
#include <linux/spinlock.h>
#include <linux/semaphore.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/circ_buf.h>
#include "drv_xcan.h"
#endif  // (defined(EN_CAN) || defined(EN_CANFD))
#include "drv_cdev.h"

// struct cdev_dev_t canfd_cdev[CANFD_DEV_NUM];
// struct cdev_ctrl_t canfd_cdev_ctrl;
// struct xcan_dev_t xcanfd_dev[CANFD_DEV_NUM];
// struct cdev_dev_t can_cdev[CAN_DEV_NUM];
// struct cdev_ctrl_t can_cdev_ctrl;
// struct xcan_dev_t xcan_dev[CAN_DEV_NUM];

#define XCAN_MSI_MASK           0x01            /* MSI 中断屏蔽 掩码 */
#define XCANFD_MSI_VEC_START    1               /* CANFD 中断向量起始值 */
#define XCAN_MSI_VEC_START      4               /* CAN 中断向量起始值 */

/* XCAN 寄存器*/
enum xcan_reg {
    XCAN_VERSION_OFFSET         = 0x04,         /* 版本号 寄存器 */
    XCAN_MSI_MASK_OFFSET        = 0x60,         /* MSI 中断屏蔽 寄存器偏移 */
};

/* CAN Bittiming constants as per Xilinx CAN specs */
const struct can_bittiming_const xcan_bittiming_const = {
	// .name = CAN_DRV_NAME,
	.tseg1_min = 1,
	.tseg1_max = 16,
	.tseg2_min = 1,
	.tseg2_max = 8,
	.sjw_max = 4,
	.brp_min = 4,
	.brp_max = 256,
	.brp_inc = 1,
};

/* AXI CANFD 2.0 Arbitration Bittiming constants as per AXI CANFD 2.0 spec */
const struct can_bittiming_const xcan_bittiming_const_canfd2 = {
	// .name = CANFD_DRV_NAME,
	.tseg1_min = 1,
	.tseg1_max = 256,
	.tseg2_min = 1,
	.tseg2_max = 128,
	.sjw_max = 128,
	.brp_min = 1,
	.brp_max = 256,
	.brp_inc = 1,
};
/* AXI CANFD 2.0 Data Bittiming constants as per AXI CANFD 2.0 spec */
const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
	// .name = CANFD_DRV_NAME,
	.tseg1_min = 1,
	.tseg1_max = 32,
	.tseg2_min = 1,
	.tseg2_max = 16,
	.sjw_max = 16,
	.brp_min = 1,
	.brp_max = 256,
	.brp_inc = 1,
};

const struct xcan_devtype_data xcan_axi_data = {
	.bittiming_const = &xcan_bittiming_const,
	.btr_ts2_shift = XCAN_BTR_TS2_SHIFT,
	.btr_sjw_shift = XCAN_BTR_SJW_SHIFT,
	.bus_clk_name = "s_axi_aclk",
};

const struct xcan_devtype_data xcan_canfd2_data = {
	.cantype = XAXI_CANFD_2_0,
	.flags = XCAN_FLAG_EXT_FILTERS |
		 XCAN_FLAG_RXMNF |
		 XCAN_FLAG_TX_MAILBOXES |
		 XCAN_FLAG_CANFD_2 |
		 XCAN_FLAG_RX_FIFO_MULTI,
	.bittiming_const = &xcan_bittiming_const_canfd2,
	.btr_ts2_shift = XCAN_BTR_TS2_SHIFT_CANFD,
	.btr_sjw_shift = XCAN_BTR_SJW_SHIFT_CANFD,
	.bus_clk_name = "s_axi_aclk",
};

/* 文件操作函数声明 */
static int open_xcan(struct inode *inode, struct file *filp);
static int release_xcan(struct inode *inode, struct file *filp);
static ssize_t read_xcan(struct file *filp, char __user *buf, 
                              size_t count, loff_t *ppos);
static ssize_t write_xcan(struct file *filp, const char __user *buf, 
                               size_t count, loff_t *ppos);
static long ioctl_xcan(struct file *filp, unsigned int cmd, 
                            unsigned long arg);
static irqreturn_t xcan_interrupt(int irq, void *dev_id);

/* 文件操作结构体 */
static const struct file_operations cdev_fops = {
    .owner = THIS_MODULE,
    .open = open_xcan,
    .release = release_xcan,
    .read = read_xcan,
    .write = write_xcan,
    .unlocked_ioctl = ioctl_xcan,
    .poll = NULL,
    .llseek = no_llseek, // 不支持 seek
};

static int xcan_frame_to_msg(struct canfd_frame cf, struct canfd_msg_t *msg)
{
    int ret = 0;

    if (!msg) {
        pr_err("Error: Null pointer provided for canfd_msg");
        return -1;
    }
    memset(msg, 0, sizeof(struct canfd_msg_t));
    
    /* 打印输入帧的详细信息 */
    pr_debug("can_id=0x%x, len=%u, flags=0x%x",
           cf.can_id, cf.len, cf.flags);
    pr_debug("data=%*ph", cf.len, cf.data);

    /*
     * 32 bit CAN_ID + EFF/RTR/ERR flags
     *
     * bit 0-28  : CAN identifier (11/29 bit)
     * bit 29    : error message frame flag (0 = data frame, 1 = error message)
     * bit 30    : remote transmission request flag (1 = rtr frame)
     * bit 31    : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
     */
    if (cf.can_id & CAN_EFF_FLAG) {
        msg->fmt = 1;
    } else {
        msg->fmt = 0;
    }
    if (cf.can_id & CAN_RTR_FLAG) {
        msg->rtr = 1;
    } else {
        msg->rtr = 0;
    }
    msg->id = (((cf.can_id & ~CAN_EFF_FLAG) & ~CAN_RTR_FLAG) & ~CAN_ERR_FLAG);
    /* frame payload length in byte */
    msg->dlc = cf.len;
    /* additional flags for CAN FD */
    msg->flg = cf.flags;
    memcpy(msg->data, cf.data, cf.len);

    /* 打印输出消息的详细信息 */
    pr_debug("msg.fmt=%u, msg.rtr=%u, msg.id=0x%lx, msg.dlc=%u, msg.flg=%d",
           msg->fmt, msg->rtr, msg->id, msg->dlc, msg->flg);
    pr_debug("msg.data=%*ph", msg->dlc, msg->data);
    return ret;
}

static int xcan_msg_to_frame(struct canfd_msg_t msg, struct canfd_frame *cf)
{
    int ret = 0;

    if (!cf) {
        pr_err("Error: Null pointer provided for canfd_frame");
        return -1;
    }
    memset(cf, 0, sizeof(struct canfd_frame));
    
    /* 打印输入消息的详细信息 */
    pr_debug("msg.fmt=%u, msg.rtr=%u, msg.id=0x%lx, msg.dlc=%u, msg.flg=%d",
           msg.fmt, msg.rtr, msg.id, msg.dlc, msg.flg);
    pr_debug("msg.data=%*ph", msg.dlc, msg.data);

    /*
     * 32 bit CAN_ID + EFF/RTR/ERR flags
     *
     * bit 0-28  : CAN identifier (11/29 bit)
     * bit 29    : error message frame flag (0 = data frame, 1 = error message)
     * bit 30    : remote transmission request flag (1 = rtr frame)
     * bit 31    : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
     */
    if (0 == msg.fmt) {
        cf->can_id = msg.id;
        if (1 == msg.rtr)
            cf->can_id |= CAN_RTR_FLAG;
    } else {
        cf->can_id = msg.id;
        cf->can_id |= CAN_EFF_FLAG;
        if (1 == msg.rtr)
            cf->can_id |= CAN_RTR_FLAG;
    }
    /* frame payload length in byte */
    cf->len = msg.dlc;
    /* additional flags for CAN FD */
    cf->flags = msg.flg;
    memcpy(cf->data, msg.data, msg.dlc);

    /* 打印输出帧的详细信息 */
    pr_debug("  can_id = 0x%x, len = %u, flags = 0x%x",
           cf->can_id, cf->len, cf->flags);
    pr_debug("  data = %*ph", cf->len, cf->data);

    return ret;
}

/* 检查缓冲区是否为空 */
static int circ_buf_empty(struct circ_buf_t *rx_circ) {
    return (rx_circ->head == rx_circ->tail);
}
/* 检查缓冲区是否已满 */
static int circ_buf_full(struct circ_buf_t *rx_circ) {
    return (((rx_circ->head + 1) % rx_circ->size) == rx_circ->tail);
}

/**
 * xcan_write_reg_le - Write a value to the device register little endian
 * @priv:	Driver private data structure
 * @reg:	Register offset
 * @val:	Value to write at the Register offset
 *
 * Write data to the paricular CAN register
 */
static void xcan_write_reg_le(struct xcan_dev_t *priv, enum xcan_core_reg reg, u32 val)
{
    struct xcan_ctrl_t *pctrl = priv->parent;
    struct pcie_dev_t *ppdev = pctrl->ppdev;
    unsigned long flags;

    void __iomem *addr_reg = priv->reg_base + priv->wr_addr_reg;
    void __iomem *data_reg = priv->reg_base + priv->wr_data_reg;
    u32 wreg = 0;

    spin_lock_irqsave(&ppdev->splock, flags);
    wreg = ((priv->index) << CANFD_DEV_ID_SHIFT | reg);
    iowrite32(wreg, addr_reg);      /* 写寄存器地址 */
    udelay(1);
    iowrite32(val, data_reg);       /* 写寄存器数据 */
    spin_unlock_irqrestore(&ppdev->splock, flags);
    // dev_dbg(priv->dev, "Write: id=%d, reg=0x%04x, val=0x%08x", priv->index, reg, val);
}

static void write_xcan_mem_le(void __iomem *mem, u32 offset, u32 val)
{
    void __iomem *vir_mem = NULL;

    vir_mem = mem + offset;
    iowrite32(val, vir_mem);
    pr_debug("Write: mem=0x%px, val=0x%08x", vir_mem, val);
}

/**
 * xcan_read_reg_le - Read a value from the device register little endian
 * @priv:	Driver private data structure
 * @reg:	Register offset
 *
 * Read data from the particular CAN register
 * Return: value read from the CAN register
 */
static u32 xcan_read_reg_le(struct xcan_dev_t *priv, enum xcan_core_reg reg)
{
    struct xcan_ctrl_t *pctrl = priv->parent;
    struct pcie_dev_t *ppdev = pctrl->ppdev;
    unsigned long flags;

    void __iomem *addr_reg = priv->reg_base + priv->rd_addr_reg;
    void __iomem *data_reg = priv->reg_base + priv->rd_data_reg;
    u32 rreg = 0;
    u32 rval = 0;

    spin_lock_irqsave(&ppdev->splock, flags);
    rreg = ((priv->index) << CANFD_DEV_ID_SHIFT | reg);
    iowrite32(rreg, addr_reg);       /* 读寄存器地址 */
    udelay(1);
    rval = ioread32(data_reg);       /* 读寄存器数据 */
    spin_unlock_irqrestore(&ppdev->splock, flags);
    // dev_dbg(priv->dev, "Read:  id=%d, reg=0x%04x, val=0x%08x", priv->index, reg, rval);

    return rval;
}

static u32 read_xcan_mem_le(void __iomem *mem, u32 offset)
{
    void __iomem *vir_mem = NULL;
    u32 val = 0;

    vir_mem = mem + offset;
    val = ioread32(vir_mem);;
    pr_debug("Read:  mem=0x%px, val=0x%08x", vir_mem, val);

    return val;
}

/* 读取 DI 寄存器 */
static u32 read_xcan_reg_le(struct pcie_dev_t *ppdev, u32 reg)
{
    u32 val = 0;
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&ppdev->splock, flags);
    val = ioread32(ppdev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&ppdev->splock, flags);
    pr_debug("%s  reg=0x%04x, val=0x%08x", __func__, reg, val);

    return val;
}

/* 写入 DI 寄存器 */
static void write_xcan_reg_le(struct pcie_dev_t *ppdev, u32 reg, u32 val)
{
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&ppdev->splock, flags);
    iowrite32(val, ppdev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&ppdev->splock, flags);
    pr_debug("%s reg=0x%04x, val=0x%08x", __func__, reg, val);
}

/* 使能 MSI 中断 */
static int enable_msi_irq(struct xcan_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->ppdev, XCAN_MSI_MASK_OFFSET);
    val |= XCAN_MSI_MASK;
    pctrl->write_reg(pctrl->ppdev, XCAN_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 禁用 MSI 中断 */
static int disable_msi_irq(struct xcan_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->ppdev, XCAN_MSI_MASK_OFFSET);
    val &= (~XCAN_MSI_MASK);
    pctrl->write_reg(pctrl->ppdev, XCAN_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/**
 * xcan_rx_int_mask - Get the mask for the receive interrupt
 * @priv:	Driver private data structure
 *
 * Return: The receive interrupt mask used by the driver on this HW
 */
static u32 xcan_rx_int_mask(const struct xcan_dev_t *priv)
{
	/* RXNEMP is better suited for our use case as it cannot be cleared
	 * while the FIFO is non-empty, but CAN FD HW does not have it
	 */
	if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI)
		return XCAN_IXR_RXOK_MASK;
	else
		return XCAN_IXR_RXNEMP_MASK;
}
/**
 * set_reset_mode - Resets the CAN device mode
 * @ndev:	Pointer to net_device structure
 *
 * This is the driver reset mode routine.The driver
 * enters into configuration mode.
 *
 * Return: 0 on success and failure value on error
 */
static int set_reset_mode(struct xcan_dev_t *priv)
{
	unsigned long timeout;

	priv->write_ipcore(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
    /* 执行软复位或硬复位后，请等待 16 个 AXI4-Lite/APB 时钟周期，
     * 然后再启动下一个 AXI4-Lite/APB 事务。
     */
    udelay(10);

    // dev_info(priv->dev, "SRR=0x%08x, SR=0x%08x",
    //          priv->read_ipcore(priv, XCAN_SRR_OFFSET),
    //          priv->read_ipcore(priv, XCAN_SR_OFFSET));
    dev_info(priv->dev, "%s SR=0x%08x", __func__, 
             priv->read_ipcore(priv, XCAN_SR_OFFSET));

	timeout = jiffies + XCAN_TIMEOUT;
	while (!(priv->read_ipcore(priv, XCAN_SR_OFFSET) & XCAN_SR_CONFIG_MASK)) {
		if (time_after(jiffies, timeout)) {
			dev_warn(priv->dev, "timed out for config mode");

            dev_info(priv->dev, "%s SRR=0x%08x, SR=0x%08x", __func__, 
                    priv->read_ipcore(priv, XCAN_SRR_OFFSET),
                    priv->read_ipcore(priv, XCAN_SR_OFFSET));

			return -ETIMEDOUT;
		}
		usleep_range(500, 10000);
	}

	/* reset clears FIFOs */
	// priv->tx_head = 0;
	// priv->tx_tail = 0;
    priv->rx_circ.head = 0;
    priv->rx_circ.tail = 0;
    priv->tx_circ.head = 0;
    priv->tx_circ.tail = 0;

	return 0;
}

/**
 * xcan_set_bittiming - CAN set bit timing routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the driver set bittiming  routine.
 * Return: 0 on success and failure value on error
 */
static int xcan_set_bittiming(struct xcan_dev_t *priv)
{
	struct can_bittiming *bt = &priv->can.bittiming;
	struct can_bittiming *dbt = &priv->can.data_bittiming;
	u32 btr0, btr1;
	u32 is_config_mode;

	/* Check whether Xilinx CAN is in configuration mode.
	 * It cannot set bit timing if Xilinx CAN is not in configuration mode.
	 */
	is_config_mode = priv->read_ipcore(priv, XCAN_SR_OFFSET) &
				XCAN_SR_CONFIG_MASK;
	if (!is_config_mode) {
		dev_warn(priv->dev,
			     "BUG! Cannot set bittiming - CAN is not in config mode");
		return -EPERM;
	}

	/* Setting Baud Rate prescalar value in BRPR Register */
	btr0 = (bt->brp - 1);

	/* Setting Time Segment 1 in BTR Register */
	btr1 = (bt->prop_seg + bt->phase_seg1 - 1);

	/* Setting Time Segment 2 in BTR Register */
	btr1 |= (bt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift;

	/* Setting Synchronous jump width in BTR Register */
	btr1 |= (bt->sjw - 1) << priv->devtype.btr_sjw_shift;

	priv->write_ipcore(priv, XCAN_BRPR_OFFSET, btr0);
	priv->write_ipcore(priv, XCAN_BTR_OFFSET, btr1);

	if (priv->devtype.cantype == XAXI_CANFD ||
	    priv->devtype.cantype == XAXI_CANFD_2_0) {
		/* Setting Baud Rate prescalar value in F_BRPR Register */
		btr0 = dbt->brp - 1;

		/* Setting Time Segment 1 in BTR Register */
		btr1 = dbt->prop_seg + dbt->phase_seg1 - 1;

		/* Setting Time Segment 2 in BTR Register */
		btr1 |= (dbt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift;

		/* Setting Synchronous jump width in BTR Register */
		btr1 |= (dbt->sjw - 1) << priv->devtype.btr_sjw_shift;

		priv->write_ipcore(priv, XCAN_F_BRPR_OFFSET, btr0);
		priv->write_ipcore(priv, XCAN_F_BTR_OFFSET, btr1);

		dev_info(priv->dev, "%s DATA_BRPR=0x%08x, DATA_BTR=0x%08x", __func__, 
			   priv->read_ipcore(priv, XCAN_F_BRPR_OFFSET),
			   priv->read_ipcore(priv, XCAN_F_BTR_OFFSET));
	}

	dev_info(priv->dev, "%s BRPR=0x%08x, BTR=0x%08x", __func__, 
		   priv->read_ipcore(priv, XCAN_BRPR_OFFSET),
		   priv->read_ipcore(priv, XCAN_BTR_OFFSET));

	return 0;
}

/**
 * xcan_chip_start - This the drivers start routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the drivers start routine.
 * Based on the State of the CAN device it puts
 * the CAN device into a proper mode.
 *
 * Return: 0 on success and failure value on error
 */
static int xcan_chip_start(struct xcan_dev_t *priv)
{
	u32 reg_msr;
	int err;
	u32 ier;

	/* Check if it is in reset mode */
	err = set_reset_mode(priv);
	if (err < 0) {
        dev_err(priv->dev, "%s set %s reset mode failed", __func__, priv->name);
		return err;
    }

	err = xcan_set_bittiming(priv);
	if (err < 0) {
        dev_err(priv->dev, "%s set %s bittiming failed", __func__, priv->name);
		return err;
    }

	/* Enable interrupts
	 *
	 * We enable the ERROR interrupt even with
	 * CAN_CTRLMODE_BERR_REPORTING disabled as there is no
	 * dedicated interrupt for a state change to
	 * ERROR_WARNING/ERROR_PASSIVE.
	 */
	ier = XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |
		XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK |
		XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
		XCAN_IXR_ARBLST_MASK | xcan_rx_int_mask(priv);

	if (priv->devtype.flags & XCAN_FLAG_RXMNF)
		ier |= XCAN_IXR_RXMNF_MASK;

	priv->write_ipcore(priv, XCAN_IER_OFFSET, ier);

	/* Check whether it is loopback mode or normal mode  */
	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
		reg_msr = XCAN_MSR_LBACK_MASK;
	else
		reg_msr = 0x0;

	/* enable the first extended filter, if any, as cores with extended
	 * filtering default to non-receipt if all filters are disabled
	 */
	if (priv->devtype.flags & XCAN_FLAG_EXT_FILTERS)
		priv->write_ipcore(priv, XCAN_AFR_EXT_OFFSET, 0x00000001);

	priv->write_ipcore(priv, XCAN_MSR_OFFSET, reg_msr);
	priv->write_ipcore(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK);

	dev_info(priv->dev, "%s status:#x%08x", __func__, 
		   priv->read_ipcore(priv, XCAN_SR_OFFSET));

	priv->can.state = CAN_STATE_ERROR_ACTIVE;
	return 0;
}
/**
 * xcan_do_set_mode - This sets the mode of the driver
 * @ndev:	Pointer to net_device structure
 * @mode:	Tells the mode of the driver
 *
 * This check the drivers state and calls the
 * the corresponding modes to set.
 *
 * Return: 0 on success and failure value on error
 */
int xcan_do_set_mode(struct xcan_dev_t *priv, enum can_mode mode)
{
	int ret;

	switch (mode) {
	case CAN_MODE_START:
		ret = xcan_chip_start(priv);
		if (ret < 0) {
			dev_err(priv->dev, "%s start %s chip failed", __func__, priv->name);
			return ret;
		}
		// netif_wake_queue(ndev);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}

	return ret;
}
/**
 * xcan_write_frame - Write a frame to HW
 * @ndev:		Pointer to net_device structure
 * @skb:		sk_buff pointer that contains data to be Txed
 * @frame_offset:	Register offset to write the frame to
 */
static void xcan_write_frame(struct xcan_dev_t *priv, struct canfd_frame *buf, 
			     int frame_offset)
{
	u32 id, dlc, data[2] = {0, 0};
	struct canfd_frame *cf = buf;
	u32 ramoff, dwindex = 0, i;

	/* Watch carefully on the bit sequence */
	if (cf->can_id & CAN_EFF_FLAG) {
		/* Extended CAN ID format */
		id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) &
			XCAN_IDR_ID2_MASK;
		id |= (((cf->can_id & CAN_EFF_MASK) >>
			(CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)) <<
			XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK;

		/* The substibute remote TX request bit should be "1"
		 * for extended frames as in the Xilinx CAN datasheet
		 */
		id |= XCAN_IDR_IDE_MASK | XCAN_IDR_SRR_MASK;

		if (cf->can_id & CAN_RTR_FLAG)
			/* Extended frames remote TX request */
			id |= XCAN_IDR_RTR_MASK;
	} else {
		/* Standard CAN ID format */
		id = ((cf->can_id & CAN_SFF_MASK) << XCAN_IDR_ID1_SHIFT) &
			XCAN_IDR_ID1_MASK;

		if (cf->can_id & CAN_RTR_FLAG)
			/* Standard frames remote TX request */
			id |= XCAN_IDR_SRR_MASK;
	}

	dlc = can_len2dlc(cf->len) << XCAN_DLCR_DLC_SHIFT;
	// if (can_is_canfd_skb(skb)) {
	if (1 == cf->flags) {
		if (cf->flags & CANFD_BRS)
			dlc |= XCAN_DLCR_BRS_MASK;
		dlc |= XCAN_DLCR_EDL_MASK;
	}

	// if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
	//     (priv->devtype.flags & XCAN_FLAG_TXFEMP))
	// 	can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
	// else
	// 	can_put_echo_skb(skb, ndev, 0);

	// priv->tx_head++;
    priv->tx_circ.head = (priv->tx_circ.head + 1) & (priv->tx_circ.size - 1);

	priv->write_ipcore(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
	/* If the CAN frame is RTR frame this write triggers transmission
	 * (not on CAN FD)
	 */
	priv->write_ipcore(priv, XCAN_FRAME_DLC_OFFSET(frame_offset), dlc);
	if (priv->devtype.cantype == XAXI_CANFD ||
	    priv->devtype.cantype == XAXI_CANFD_2_0) {
		for (i = 0; i < cf->len; i += 4) {
			ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset) +
					(dwindex * XCANFD_DW_BYTES);
			priv->write_ipcore(priv, ramoff,
					be32_to_cpup((__be32 *)(cf->data + i)));
			dwindex++;
		}
	} else {
		if (cf->len > 0)
			data[0] = be32_to_cpup((__be32 *)(cf->data + 0));
		if (cf->len > 4)
			data[1] = be32_to_cpup((__be32 *)(cf->data + 4));

		if (!(cf->can_id & CAN_RTR_FLAG)) {
			priv->write_ipcore(priv,
					XCAN_FRAME_DW1_OFFSET(frame_offset),
					data[0]);
			/* If the CAN frame is Standard/Extended frame this
			 * write triggers transmission (not on CAN FD)
			 */
			priv->write_ipcore(priv,
					XCAN_FRAME_DW2_OFFSET(frame_offset),
					data[1]);
		}
        /* only pango use */
        priv->write_ipcore(priv,
                        XCAN_FIFO_CTRL_OFFSET,
                        XCAN_FIFO_CR_TFC_MASK);
	}
}

/**
 * xcan_start_xmit_fifo - Starts the transmission (FIFO mode)
 * @skb:	sk_buff pointer that contains data to be Txed
 * @ndev:	Pointer to net_device structure
 *
 * Return: 0 on success, -ENOSPC if FIFO is full.
 */
static int xcan_start_xmit_fifo(struct canfd_frame *buf, struct xcan_dev_t *priv)
{
	unsigned long flags;

	/* Check if the TX buffer is full */
	if (unlikely(priv->read_ipcore(priv, XCAN_SR_OFFSET) &
			XCAN_SR_TXFLL_MASK))
		return -ENOSPC;

	spin_lock_irqsave(&priv->tx_lock, flags);

	xcan_write_frame(priv, buf, XCAN_TXFIFO_OFFSET);

	/* Clear TX-FIFO-empty interrupt for xcan_tx_interrupt() */
	if (priv->tx_max > 1)
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXFEMP_MASK);

	/* Check if the TX buffer is full */
	// if ((priv->tx_head - priv->tx_tail) == priv->tx_max)
	// 	netif_stop_queue(ndev);
    if (circ_buf_full(&priv->tx_circ)) {
        dev_dbg(priv->dev, "tx buffer full");
    }

	spin_unlock_irqrestore(&priv->tx_lock, flags);

	return 0;
}

/**
 * xcan_start_xmit_mailbox - Starts the transmission (mailbox mode)
 * @skb:	sk_buff pointer that contains data to be Txed
 * @ndev:	Pointer to net_device structure
 *
 * Return: 0 on success, -ENOSPC if there is no space
 */
static int xcan_start_xmit_mailbox(struct canfd_frame *buf, struct xcan_dev_t *priv)
{
	unsigned long flags;

	if (unlikely(priv->read_ipcore(priv, XCAN_TRR_OFFSET) &
		     BIT(XCAN_TX_MAILBOX_IDX)))
		return -ENOSPC;

	spin_lock_irqsave(&priv->tx_lock, flags);

	xcan_write_frame(priv, buf, 
			 XCAN_TXMSG_FRAME_OFFSET(XCAN_TX_MAILBOX_IDX));

	/* Mark buffer as ready for transmit */
	priv->write_ipcore(priv, XCAN_TRR_OFFSET, BIT(XCAN_TX_MAILBOX_IDX));

	// netif_stop_queue(ndev);

	spin_unlock_irqrestore(&priv->tx_lock, flags);

	return 0;
}

/**
 * xcan_start_xmit - Starts the transmission
 * @skb:	sk_buff pointer that contains data to be Txed
 * @ndev:	Pointer to net_device structure
 *
 * This function is invoked from upper layers to initiate transmission.
 *
 * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY when the tx queue is full
 */
static int xcan_start_xmit(struct canfd_frame *buf, struct xcan_dev_t *priv)
{
	int ret;

	if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES)
		ret = xcan_start_xmit_mailbox(buf, priv);
	else
		ret = xcan_start_xmit_fifo(buf, priv);

	if (ret < 0) {
		dev_err(priv->dev, "BUG!, TX full when queue awake");
		// netif_stop_queue(ndev);
		return -1;
	}

	return 0;
}
/**
 * xcan_rx -  Is called from CAN isr to complete the received
 *		frame  processing
 * @ndev:	Pointer to net_device structure
 * @frame_base:	Register offset to the frame to be read
 *
 * This function is invoked from the CAN isr(poll) to process the Rx frames. It
 * does minimal processing and invokes "netif_receive_skb" to complete further
 * processing.
 * Return: 1 on success and 0 on failure.
 */
static int xcan_rx(struct xcan_dev_t *priv, int frame_base)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	struct xcan_device_stats *stats = &priv->stats;
	struct can_frame *cf = (struct can_frame *)&priv->rx_frame;
	// struct sk_buff *skb;
	u32 id_xcan, dlc, data[2] = {0, 0};
    unsigned long flags;

	// skb = alloc_can_skb(ndev, &cf);
	// if (unlikely(!skb)) {
	// 	stats->rx_dropped++;
	// 	return 0;
	// }

	/* Read a frame from Xilinx zynq CANPS */
	id_xcan = priv->read_ipcore(priv, XCAN_FRAME_ID_OFFSET(frame_base));
	dlc = priv->read_ipcore(priv, XCAN_FRAME_DLC_OFFSET(frame_base)) >>
				   XCAN_DLCR_DLC_SHIFT;

	/* Change Xilinx CAN data length format to socketCAN data format */
	cf->can_dlc = get_can_dlc(dlc);

	/* Change Xilinx CAN ID format to socketCAN ID format */
	if (id_xcan & XCAN_IDR_IDE_MASK) {
		/* The received frame is an Extended format frame */
		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3;
		cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >>
				XCAN_IDR_ID2_SHIFT;
		cf->can_id |= CAN_EFF_FLAG;
		if (id_xcan & XCAN_IDR_RTR_MASK)
			cf->can_id |= CAN_RTR_FLAG;
	} else {
		/* The received frame is a standard format frame */
		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >>
				XCAN_IDR_ID1_SHIFT;
		if (id_xcan & XCAN_IDR_SRR_MASK)
			cf->can_id |= CAN_RTR_FLAG;
	}

	/* DW1/DW2 must always be read to remove message from RXFIFO */
	data[0] = priv->read_ipcore(priv, XCAN_FRAME_DW1_OFFSET(frame_base));
	data[1] = priv->read_ipcore(priv, XCAN_FRAME_DW2_OFFSET(frame_base));
    /* only pango use */
    priv->write_ipcore(priv, XCAN_FIFO_CTRL_OFFSET, XCAN_FIFO_CR_RFC_MASK);

	if (!(cf->can_id & CAN_RTR_FLAG)) {
		/* Change Xilinx CAN data format to socketCAN data format */
		if (cf->can_dlc > 0)
			*(__be32 *)(cf->data) = cpu_to_be32(data[0]);
		if (cf->can_dlc > 4)
			*(__be32 *)(cf->data + 4) = cpu_to_be32(data[1]);
	}

	stats->rx_bytes += cf->can_dlc;
	stats->rx_packets++;
	// netif_receive_skb(skb);

    spin_lock_irqsave(&priv->rx_splock, flags);
    xcan_frame_to_msg(*(struct canfd_frame *)cf, &priv->rx_circ.msg[priv->rx_circ.head]);
    if (circ_buf_full(&priv->rx_circ)) {
        /* 丢弃最旧数据，位运算 & 比取模运算 % 快 10 倍以上（CPU 指令周期更少） */
        // priv->rx_circ.tail = (priv->rx_circ.tail + 1) % priv->rx_circ.size;
        priv->rx_circ.tail = (priv->rx_circ.tail + 1) & (priv->rx_circ.size - 1);
    }
    priv->rx_circ.head = (priv->rx_circ.head + 1) & (priv->rx_circ.size - 1);
    spin_unlock_irqrestore(&priv->rx_splock, flags);
    wake_up_interruptible(&priv->rx_wqh);

	return 1;
}

/**
 * xcanfd_rx -  Is called from CAN isr to complete the received
 *		frame  processing
 * @ndev:	Pointer to net_device structure
 * @frame_base:	Register offset to the frame to be read
 *
 * This function is invoked from the CAN isr(poll) to process the Rx frames. It
 * does minimal processing and invokes "netif_receive_skb" to complete further
 * processing.
 * Return: 1 on success and 0 on failure.
 */
static int xcanfd_rx(struct xcan_dev_t *priv, int frame_base)
{
	struct canfd_frame *cf = &priv->rx_frame;
	u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, dw_offset;
    unsigned long flags;    // 用于保存中断状态

	id_xcan = priv->read_ipcore(priv, XCAN_FRAME_ID_OFFSET(frame_base));
	dlc = priv->read_ipcore(priv, XCAN_FRAME_DLC_OFFSET(frame_base));

	/* Change Xilinx CANFD data length format to socketCAN data
	 * format
	 */
	if (dlc & XCAN_DLCR_EDL_MASK)
		cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >>
				  XCAN_DLCR_DLC_SHIFT);
	else
		cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >>
					  XCAN_DLCR_DLC_SHIFT);

	/* Change Xilinx CAN ID format to socketCAN ID format */
	if (id_xcan & XCAN_IDR_IDE_MASK) {
		/* The received frame is an Extended format frame */
		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3;
		cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >>
				XCAN_IDR_ID2_SHIFT;
		cf->can_id |= CAN_EFF_FLAG;
		if (id_xcan & XCAN_IDR_RTR_MASK)
			cf->can_id |= CAN_RTR_FLAG;
	} else {
		/* The received frame is a standard format frame */
		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >>
				XCAN_IDR_ID1_SHIFT;
		if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan &
					XCAN_IDR_SRR_MASK))
			cf->can_id |= CAN_RTR_FLAG;
	}

	/* Check the frame received is FD or not*/
	if (dlc & XCAN_DLCR_EDL_MASK) {
        cf->flags = 1;      /* CANFD */
		for (i = 0; i < cf->len; i += 4) {
			dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) +
					(dwindex * XCANFD_DW_BYTES);
			data[0] = priv->read_ipcore(priv, dw_offset);
			*(__be32 *)(cf->data + i) = cpu_to_be32(data[0]);
			dwindex++;
		}
	} else {
        cf->flags = 0;      /* CANFD */
		for (i = 0; i < cf->len; i += 4) {
			dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base);
			data[0] = priv->read_ipcore(priv, dw_offset + i);
			*(__be32 *)(cf->data + i) = cpu_to_be32(data[0]);
		}
	}

    // 环形缓冲区操作
    spin_lock_irqsave(&priv->rx_splock, flags);
    // if (id_xcan & XCAN_IDR_IDE_MASK) {
    //     priv->rx_circ.msg[priv->rx_circ.head].fmt = 1;
    // } else {
    //     priv->rx_circ.msg[priv->rx_circ.head].fmt = 0;
    // }
    // if (id_xcan & XCAN_IDR_RTR_MASK) {
    //     priv->rx_circ.msg[priv->rx_circ.head].rtr = 1;
    // } else {
    //     priv->rx_circ.msg[priv->rx_circ.head].rtr = 0;
    // }
    // priv->rx_circ.msg[priv->rx_circ.head].id = ((cf->can_id & ~CAN_EFF_FLAG) & ~CAN_RTR_FLAG);
    // priv->rx_circ.msg[priv->rx_circ.head].dlc = cf->len;
    // if (dlc & XCAN_DLCR_EDL_MASK) {
    //     priv->rx_circ.msg[priv->rx_circ.head].flg = 1;
    // } else {
    //     priv->rx_circ.msg[priv->rx_circ.head].flg = 0;
    // }
    // for (i = 0; i < priv->rx_circ.msg[priv->rx_circ.head].dlc; i++) {
    //     priv->rx_circ.msg[priv->rx_circ.head].data[i] = cf->data[i];
    // }
    xcan_frame_to_msg(*cf, &priv->rx_circ.msg[priv->rx_circ.head]);

    if (circ_buf_full(&priv->rx_circ)) {
        /* 丢弃最旧数据，位运算 & 比取模运算 % 快 10 倍以上（CPU 指令周期更少） */
        // priv->rx_circ.tail = (priv->rx_circ.tail + 1) % priv->rx_circ.size;
        priv->rx_circ.tail = (priv->rx_circ.tail + 1) & (priv->rx_circ.size - 1);
    }
    priv->rx_circ.head = (priv->rx_circ.head + 1) & (priv->rx_circ.size - 1);
    spin_unlock_irqrestore(&priv->rx_splock, flags);
    wake_up_interruptible(&priv->rx_wqh);

    return 1;
}
/**
 * xcan_current_error_state - Get current error state from HW
 * @ndev:	Pointer to net_device structure
 *
 * Checks the current CAN error state from the HW. Note that this
 * only checks for ERROR_PASSIVE and ERROR_WARNING.
 *
 * Return:
 * ERROR_PASSIVE or ERROR_WARNING if either is active, ERROR_ACTIVE
 * otherwise.
 */
static enum can_state xcan_current_error_state(struct xcan_dev_t *priv)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	u32 status = priv->read_ipcore(priv, XCAN_SR_OFFSET);

	if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK)
		return CAN_STATE_ERROR_PASSIVE;
	else if (status & XCAN_SR_ERRWRN_MASK)
		return CAN_STATE_ERROR_WARNING;
	else
		return CAN_STATE_ERROR_ACTIVE;
}
/**
 * xcan_set_error_state - Set new CAN error state
 * @ndev:	Pointer to net_device structure
 * @new_state:	The new CAN state to be set
 * @cf:		Error frame to be populated or NULL
 *
 * Set new CAN error state for the device, updating statistics and
 * populating the error frame if given.
 */
static void xcan_set_error_state(struct xcan_dev_t *priv,
				 enum can_state new_state,
				 struct can_frame *cf)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	u32 ecr = priv->read_ipcore(priv, XCAN_ECR_OFFSET);
	u32 txerr = ecr & XCAN_ECR_TEC_MASK;
	u32 rxerr = (ecr & XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT;
	enum can_state tx_state = txerr >= rxerr ? new_state : 0;
	enum can_state rx_state = txerr <= rxerr ? new_state : 0;

	/* non-ERROR states are handled elsewhere */
	if (WARN_ON(new_state > CAN_STATE_ERROR_PASSIVE))
		return;

	xcan_change_state(&priv->can, cf, tx_state, rx_state);

	if (cf) {
		cf->data[6] = txerr;
		cf->data[7] = rxerr;
	}
}
/**
 * xcan_update_error_state_after_rxtx - Update CAN error state after RX/TX
 * @ndev:	Pointer to net_device structure
 *
 * If the device is in a ERROR-WARNING or ERROR-PASSIVE state, check if
 * the performed RX/TX has caused it to drop to a lesser state and set
 * the interface state accordingly.
 */
static void xcan_update_error_state_after_rxtx(struct xcan_dev_t *priv)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	enum can_state old_state = priv->can.state;
	enum can_state new_state;

	/* changing error state due to successful frame RX/TX can only
	 * occur from these states
	 */
	if (old_state != CAN_STATE_ERROR_WARNING &&
	    old_state != CAN_STATE_ERROR_PASSIVE)
		return;

	new_state = xcan_current_error_state(priv);

	if (new_state != old_state) {
#if 0
		struct sk_buff *skb;
		struct can_frame *cf;

		skb = alloc_can_err_skb(ndev, &cf);

		xcan_set_error_state(priv, new_state, skb ? cf : NULL);

		if (skb) {
			struct net_device_stats *stats = &ndev->stats;

			stats->rx_packets++;
			stats->rx_bytes += cf->can_dlc;
			netif_rx(skb);
		}
#else
        struct can_frame *cf = (struct can_frame *)&priv->rx_frame;

        /* alloc_can_err_skb 中有如下赋值 */
        cf->can_id = CAN_ERR_FLAG;
        cf->can_dlc = CAN_ERR_DLC;

        xcan_set_error_state(priv, new_state, cf);
        if (cf) {
            struct xcan_device_stats *stats = &priv->stats;

            stats->rx_packets++;
            stats->rx_bytes += cf->can_dlc;
#ifdef XCAN_BERR_REPORT
            unsigned long flags;
            /* 环形缓冲区操作 */
            spin_lock_irqsave(&priv->rx_splock, flags);
            xcan_frame_to_msg(*(struct canfd_frame *)cf, &priv->rx_circ.msg[priv->rx_circ.head]);
            if (circ_buf_full(&priv->rx_circ)) {
                /* 丢弃最旧数据，位运算 & 比取模运算 % 快 10 倍以上（CPU 指令周期更少） */
                // priv->rx_circ.tail = (priv->rx_circ.tail + 1) % priv->rx_circ.size;
                priv->rx_circ.tail = (priv->rx_circ.tail + 1) & (priv->rx_circ.size - 1);
            }
            priv->rx_circ.head = (priv->rx_circ.head + 1) & (priv->rx_circ.size - 1);
            spin_unlock_irqrestore(&priv->rx_splock, flags);
            wake_up_interruptible(&priv->rx_wqh);
#endif /* XCAN_BERR_REPORT */
        }
#endif
	}
}

/**
 * xcan_err_interrupt - error frame Isr
 * @ndev:	net_device pointer
 * @isr:	interrupt status register value
 *
 * This is the CAN error interrupt and it will
 * check the the type of error and forward the error
 * frame to upper layers.
 */
static void xcan_err_interrupt(struct xcan_dev_t *priv, u32 isr)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	struct xcan_device_stats *stats = &priv->stats;
	struct can_frame cf = { };
	u32 err_status;

	err_status = priv->read_ipcore(priv, XCAN_ESR_OFFSET);
	priv->write_ipcore(priv, XCAN_ESR_OFFSET, err_status);

	if (isr & XCAN_IXR_BSOFF_MASK) {
		priv->can.state = CAN_STATE_BUS_OFF;
		priv->can.can_stats.bus_off++;
		/* Leave device in Config Mode in bus-off state */
		priv->write_ipcore(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
		xcan_bus_off(&priv->can);
		cf.can_id |= CAN_ERR_BUSOFF;
	} else {
		enum can_state new_state = xcan_current_error_state(priv);

		if (new_state != priv->can.state)
			xcan_set_error_state(priv, new_state, &cf);
	}

	/* Check for Arbitration lost interrupt */
	if (isr & XCAN_IXR_ARBLST_MASK) {
		priv->can.can_stats.arbitration_lost++;
		cf.can_id |= CAN_ERR_LOSTARB;
		cf.data[0] = CAN_ERR_LOSTARB_UNSPEC;
	}

	/* Check for RX FIFO Overflow interrupt */
	if (isr & XCAN_IXR_RXOFLW_MASK) {
		stats->rx_over_errors++;
		stats->rx_errors++;
		cf.can_id |= CAN_ERR_CRTL;
		cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
	}

	/* Check for RX Match Not Finished interrupt */
	if (isr & XCAN_IXR_RXMNF_MASK) {
		stats->rx_dropped++;
		stats->rx_errors++;
		dev_err(priv->dev, "RX match not finished, frame discarded");
		cf.can_id |= CAN_ERR_CRTL;
		cf.data[1] |= CAN_ERR_CRTL_UNSPEC;
	}

	/* Check for error interrupt */
	if (isr & XCAN_IXR_ERROR_MASK) {
		bool berr_reporting = false;

		if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
			berr_reporting = true;
			cf.can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
		}

		/* Check for Ack error interrupt */
		if (err_status & XCAN_ESR_ACKER_MASK) {
			stats->tx_errors++;
			if (berr_reporting) {
				cf.can_id |= CAN_ERR_ACK;
				cf.data[3] = CAN_ERR_PROT_LOC_ACK;
			}
		}

		/* Check for Bit error interrupt */
		if (err_status & XCAN_ESR_BERR_MASK) {
			stats->tx_errors++;
			if (berr_reporting) {
				cf.can_id |= CAN_ERR_PROT;
				cf.data[2] = CAN_ERR_PROT_BIT;
			}
		}

		/* Check for Stuff error interrupt */
		if (err_status & XCAN_ESR_STER_MASK) {
			stats->rx_errors++;
			if (berr_reporting) {
				cf.can_id |= CAN_ERR_PROT;
				cf.data[2] = CAN_ERR_PROT_STUFF;
			}
		}

		/* Check for Form error interrupt */
		if (err_status & XCAN_ESR_FMER_MASK) {
			stats->rx_errors++;
			if (berr_reporting) {
				cf.can_id |= CAN_ERR_PROT;
				cf.data[2] = CAN_ERR_PROT_FORM;
			}
		}

		/* Check for CRC error interrupt */
		if (err_status & XCAN_ESR_CRCER_MASK) {
			stats->rx_errors++;
			if (berr_reporting) {
				cf.can_id |= CAN_ERR_PROT;
				cf.data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
			}
		}
		priv->can.can_stats.bus_error++;
	}

	if (cf.can_id) {
#if 0
		struct can_frame *skb_cf;
		struct sk_buff *skb = alloc_can_err_skb(ndev, &skb_cf);

		if (skb) {
			skb_cf->can_id |= cf.can_id;
			memcpy(skb_cf->data, cf.data, CAN_ERR_DLC);
			stats->rx_packets++;
			stats->rx_bytes += CAN_ERR_DLC;
			netif_rx(skb);
		}
#else
        /* alloc_can_err_skb 中有如下赋值 */
        cf.can_id = CAN_ERR_FLAG;
        cf.can_dlc = CAN_ERR_DLC;

        stats->rx_packets++;
        stats->rx_bytes += CAN_ERR_DLC;
#ifdef XCAN_BERR_REPORT
        unsigned long flags;
        /* 环形缓冲区操作 */
        spin_lock_irqsave(&priv->rx_splock, flags);
        xcan_frame_to_msg(*(struct canfd_frame *)&cf, &priv->rx_circ.msg[priv->rx_circ.head]);
        if (circ_buf_full(&priv->rx_circ)) {
            /* 丢弃最旧数据，位运算 & 比取模运算 % 快 10 倍以上（CPU 指令周期更少） */
            // priv->rx_circ.tail = (priv->rx_circ.tail + 1) % priv->rx_circ.size;
            priv->rx_circ.tail = (priv->rx_circ.tail + 1) & (priv->rx_circ.size - 1);
        }
        priv->rx_circ.head = (priv->rx_circ.head + 1) & (priv->rx_circ.size - 1);
        spin_unlock_irqrestore(&priv->rx_splock, flags);
        wake_up_interruptible(&priv->rx_wqh);
#endif /* XCAN_BERR_REPORT */
#endif
	}

	dev_dbg(priv->dev, "%s: error status register:0x%x",
		   __func__, priv->read_ipcore(priv, XCAN_ESR_OFFSET));
}
/**
 * xcan_state_interrupt - It will check the state of the CAN device
 * @ndev:	net_device pointer
 * @isr:	interrupt status register value
 *
 * This will checks the state of the CAN device
 * and puts the device into appropriate state.
 */
static void xcan_state_interrupt(struct xcan_dev_t *priv, u32 isr)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);

	/* Check for Sleep interrupt if set put CAN device in sleep state */
	if (isr & XCAN_IXR_SLP_MASK)
		priv->can.state = CAN_STATE_SLEEPING;

	/* Check for Wake up interrupt if set put CAN device in Active state */
	if (isr & XCAN_IXR_WKUP_MASK)
		priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
/**
 * xcan_rx_fifo_get_next_frame - Get register offset of next RX frame
 * @priv:	Driver private data structure
 *
 * Return: Register offset of the next frame in RX FIFO.
 */
static int xcan_rx_fifo_get_next_frame(struct xcan_dev_t *priv)
{
	int offset;

	if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI) {
		u32 fsr, mask;

		/* clear RXOK before the is-empty check so that any newly
		 * received frame will reassert it without a race
		 */
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXOK_MASK);

		fsr = priv->read_ipcore(priv, XCAN_FSR_OFFSET);

		/* check if RX FIFO is empty */
		if (priv->devtype.flags & XCAN_FLAG_CANFD_2)
			mask = XCAN_2_FSR_FL_MASK;
		else
			mask = XCAN_FSR_FL_MASK;

		if (!(fsr & mask))
			return -ENOENT;

		if (priv->devtype.flags & XCAN_FLAG_CANFD_2)
			offset =
			  XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_2_FSR_RI_MASK);
		else
			offset =
			  XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK);

	} else {
		/* check if RX FIFO is empty */
		if (!(priv->read_ipcore(priv, XCAN_ISR_OFFSET) &
		      XCAN_IXR_RXNEMP_MASK))
			return -ENOENT;

		/* frames are read from a static offset */
		offset = XCAN_RXFIFO_OFFSET;
	}

	return offset;
}

/* 获取状态 */
static int get_xcan_sta(struct xcan_dev_t *pdev)
{
    int ret = 0;

    pdev->reg.sr.val = pdev->read_ipcore(pdev, XCAN_SR_OFFSET);
    pdev->sta.config = pdev->reg.sr.bits.config;
    pdev->sta.lback = pdev->reg.sr.bits.lback;
    pdev->sta.sleep = pdev->reg.sr.bits.sleep;
    pdev->sta.normal = pdev->reg.sr.bits.normal;
    pdev->sta.bidle = pdev->reg.sr.bits.bidle;
    pdev->sta.bbsy = pdev->reg.sr.bits.bbsy;
    pdev->sta.errwrn = pdev->reg.sr.bits.errwrn;
    if ((pdev->reg.sr.val & XCAN_SR_ERRACT_MASK) == XCAN_SR_ERRACT_MASK) {
        pdev->sta.erract = 1;
        pdev->sta.errpsv = 0;
        pdev->sta.bsoff = 0;
    } else if ((pdev->reg.sr.val & XCAN_SR_ERRPSV_MASK) == XCAN_SR_ERRPSV_MASK) {
        pdev->sta.erract = 0;
        pdev->sta.errpsv = 1;
        pdev->sta.bsoff = 0;
    } else if ((pdev->reg.sr.val & XCAN_SR_BSOFF_MASK) == XCAN_SR_BSOFF_MASK) {
        pdev->sta.erract = 0;
        pdev->sta.errpsv = 0;
        pdev->sta.bsoff = 1;
    }
    if (pdev->devtype.cantype == XAXI_CANFD ||
        pdev->devtype.cantype == XAXI_CANFD_2_0) {
        
    } else {
        pdev->sta.txfll = pdev->reg.sr.bits.txfll;
    }
    dev_info(pdev->dev, "Get %s status reg=0x%08x, \
             \n  config(b0)=%u, \n  lback(b1)=%u, \n  sleep(b2)=%u, \n  normal(b3)=%u, \n  bidle(b4)=%u, \
             \n  bbsy(b5)=%u, \n  errwrn(b6)=%u, \n  estat(b8:7)=%u, \n  txfll(b10)=%u", 
             pdev->name, pdev->reg.sr.val, 
             pdev->reg.sr.bits.config, pdev->reg.sr.bits.lback, 
             pdev->reg.sr.bits.sleep, pdev->reg.sr.bits.normal, 
             pdev->reg.sr.bits.bidle, pdev->reg.sr.bits.bbsy, 
             pdev->reg.sr.bits.errwrn, pdev->reg.sr.bits.estat, 
             pdev->reg.sr.bits.txfll);

    return ret;
}

/* 获取错误计数 */
static int get_xcan_ecnt(struct xcan_dev_t *pdev)
{
    int ret = 0;

    pdev->reg.ecr.val = pdev->read_ipcore(pdev, XCAN_ECR_OFFSET);
    pdev->ecnt.tec = pdev->reg.ecr.bits.tec;
    pdev->ecnt.rec = pdev->reg.ecr.bits.rec;
    dev_info(pdev->dev, "Get %s ECR=0x%08x, TEC=%u, REC=%u", 
             pdev->name, pdev->reg.ecr.val, 
             pdev->reg.ecr.bits.tec, pdev->reg.ecr.bits.rec);

    return ret;
}

static int open_xcan(struct inode *inode, struct file *filp)
{
    /* 获取与 inode 关联的字符设备 */
    struct cdev_dev_t *cdev_dev = container_of(inode->i_cdev, struct cdev_dev_t, cdev);
    struct cdev_ctrl_t *cdev_ctrl = (struct cdev_ctrl_t *)cdev_dev->parent;
    struct xcan_ctrl_t *xcan_cdev = cdev_ctrl->parent;
    // struct irq_t *irq_ctrl = &xcan_cdev->irq_ctrl;
    struct xcan_dev_t *priv = &xcan_cdev->xcan[cdev_dev->index];
    int ret = 0;

    /* 检查设备是否有效 */
    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __FUNCTION__);
        return -ENODEV;
    }
    /* 记录设备指针 */
    filp->private_data = priv;
    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire %s mutex failed", cdev_dev->name);
        return -ERESTARTSYS;
    }
    dev_info(priv->dev, "Open %s%d device...", cdev_ctrl->name, cdev_dev->index);

    dev_info(priv->dev, "Version=0x%x", xcan_cdev->read_mem(xcan_cdev->ppdev->bar[0], CANFD_VERSION_REG));
    xcan_cdev->write_mem(xcan_cdev->ppdev->bar[0], CANFD_TEST_REG, 0x12345678);
    dev_info(priv->dev, "Test=0x%x", xcan_cdev->read_mem(xcan_cdev->ppdev->bar[0], CANFD_TEST_REG));

	ret = xcan_chip_start(priv);
	if (ret < 0) {
		dev_err(priv->dev, "xcan_chip_start failed");
		goto err_irq;
	} else {
        dev_info(priv->dev, "%s chip start success", xcan_cdev->name);
    }

    mutex_unlock(&priv->lock);

	return 0;

err_irq:
	// free_irq(irq_ctrl->vector[priv->index], priv);

    mutex_unlock(&priv->lock);

    return ret;
}

/* 关闭设备 */
static int release_xcan(struct inode *inode, struct file *filp)
{
    struct xcan_dev_t *priv = filp->private_data;

    if (priv) {
        mutex_lock(&priv->lock);
        dev_info(priv->dev, "Close %s device", priv->name);
        mutex_unlock(&priv->lock);
    }

    return 0;
}

/* 读取设备 */
static ssize_t read_xcan(struct file *filp, char __user *buf, 
                         size_t count, loff_t *ppos)
{
    struct xcan_dev_t *priv = filp->private_data;
    ssize_t ret = 0;
    size_t read_len = 0;
    size_t head = 0;
    size_t tail = 0;
    size_t avail = 0;
    size_t cnt_to_end = 0;      /* 到缓冲区末尾的连续数据 */
    size_t first_len = 0;       /* 第一段长度 */
    size_t second_len = 0;      /* 第二段长度 */
    unsigned long flags;        /* 用于保存中断状态 */

    /* 检查参数是否有效 */
    if (!priv || !priv->dev || !buf) {
        pr_err("Invalid parameters for %s", __FUNCTION__);
        return -EINVAL;
    }
    /* 检查偏移量是否有效 */
    if (*ppos >= priv->rx_circ.size) {
        dev_err(priv->dev, "Beyond buffer size, pos=%lld, size=%zu", 
                *ppos, priv->rx_circ.size);
        return -EFBIG;
    }

    /* 打印环形缓冲区状态 */
    dev_dbg(priv->dev, "Circular buffer state: head=%zu, tail=%zu, size=%zu", 
             priv->rx_circ.head, priv->rx_circ.tail, priv->rx_circ.size);
    
    if (circ_buf_empty(&priv->rx_circ)) {
        dev_dbg(priv->dev, "Buffer empty, waiting for data...");
        if (wait_event_interruptible(priv->rx_wqh, !circ_buf_empty(&priv->rx_circ))) {
            dev_err(priv->dev, "Wait %s read data interrupted", priv->name);
            return -ERESTARTSYS;
        }
        dev_dbg(priv->dev, "Data available after wait");
    }

    if (mutex_lock_interruptible(&priv->lock)) {
        // dev_err(priv->dev, "Acquire %s %s mutex failed", __func__, priv->name);
        dev_dbg(priv->dev, "Read %s interrupted while waiting for mutex", priv->name);
        return -ERESTARTSYS;
    }

    spin_lock_irqsave(&priv->rx_splock, flags);
    head = priv->rx_circ.head;
    tail = priv->rx_circ.tail;
    avail = CIRC_CNT(head, tail, priv->rx_circ.size);

    /* 打印计算出的可用空间 */
    dev_dbg(priv->dev, "Available data in buffer: %zu bytes", avail);
    
    if (avail == 0) {
        spin_unlock_irqrestore(&priv->rx_splock, flags);
        dev_dbg(priv->dev, "No data available after lock");
        ret = 0;
        goto unlock;
    }
    
    /* 计算实际可读取长度 */
    read_len = min(count, avail);
    cnt_to_end = CIRC_CNT(head, tail, priv->rx_circ.size);
    
    /* 分段读取 */
    first_len = min(read_len, cnt_to_end);
    second_len = read_len - first_len;
    
    /* 打印分段信息 */
    dev_dbg(priv->dev, "Read operation: total=%zu, first=%zu, second=%zu", 
             read_len, first_len, second_len);
    
    spin_unlock_irqrestore(&priv->rx_splock, flags);
    
    /* 复制第一段（缓冲区尾部） */
    if (first_len) {
        dev_dbg(priv->dev, "Copying first segment: %zu bytes from offset %zu", 
                 first_len, tail);
        if (copy_to_user(buf, &priv->rx_circ.msg[tail], first_len * sizeof(struct canfd_msg_t))) {
            dev_err(priv->dev, "Failed to copy first segment to user");
            ret = -EFAULT;
            goto unlock;
        }
    }
    
    /* 复制第二段（缓冲区头部回绕） */
    if (second_len) {
        dev_dbg(priv->dev, "Copying second segment: %zu bytes from buffer start", 
                 second_len);
        if (copy_to_user(buf + first_len, &priv->rx_circ.msg[0], second_len * sizeof(struct canfd_msg_t))) {
            dev_err(priv->dev, "Failed to copy second segment to user");
            ret = -EFAULT;
            goto unlock;
        }
    }
    
    /* 更新tail */
    spin_lock_irqsave(&priv->rx_splock, flags);
    priv->rx_circ.tail = (tail + read_len) & (priv->rx_circ.size - 1);

    dev_dbg(priv->dev, "Read %s %zu data from offset %lld", 
            priv->name, read_len, *ppos);
    /* 更新文件位置*/
    // *ppos += read_len;
    ret = read_len;
    
    /* 打印更新后的缓冲区状态 */
    dev_dbg(priv->dev, "Buffer updated: new tail=%zu, new pos=%lld", 
             priv->rx_circ.tail, *ppos);
    
    spin_unlock_irqrestore(&priv->rx_splock, flags);

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

// 写入设备
static ssize_t write_xcan(struct file *filp, const char __user *buf,
                          size_t count, loff_t *ppos)
{
    struct xcan_dev_t *priv = filp->private_data;
    ssize_t ret = 0;
    size_t write_len = 0;
    size_t head = 0;
    size_t tail = 0;
    size_t avail = 0;
    size_t cnt_to_end = 0;      /* 到缓冲区末尾的连续数据 */
    size_t first_len = 0;       /* 第一段长度 */
    size_t second_len = 0;      /* 第二段长度 */
    unsigned long flags;
    u32 i = 0;

    /* 检查参数是否有效 */
    if (!priv || !priv->dev || !buf) {
        dev_err(priv ? priv->dev : NULL, 
               "Invalid parameters: priv=%p, buf=%p", priv, buf);
        return -EINVAL;
    }
    
    dev_dbg(priv->dev, "Write request: count=%zu, pos=%lld", count, *ppos);

    /* 检查写入位置 */
    if (*ppos >= priv->tx_circ.size) {
        dev_err(priv->dev, "Write position beyond buffer size: pos=%lld, size=%zu",
               *ppos, priv->tx_circ.size);
        ret = -EFBIG;
        goto err_return;
    }

    /* 计算可用空间 */
    spin_lock_irqsave(&priv->tx_splock, flags);
    head = priv->tx_circ.head;
    tail = priv->tx_circ.tail;
    avail = CIRC_SPACE(head, tail, priv->tx_circ.size);
    dev_dbg(priv->dev, "Buffer state: head=%zu, tail=%zu, size=%zu, avail=%zu",
            head, tail, priv->tx_circ.size, avail);

    if (avail == 0) {
        spin_unlock_irqrestore(&priv->tx_splock, flags);
        dev_warn(priv->dev, "No space available in buffer");
        ret = -EAGAIN;
        goto err_return;
    }
    
    /* 计算实际可写入字节数 */
    write_len = min(count, avail);
    cnt_to_end = CIRC_SPACE(head, tail, priv->tx_circ.size);
    /* 分段写入 */
    first_len = min(write_len, cnt_to_end);
    second_len = write_len - first_len;
    
    dev_dbg(priv->dev, "Write plan: total=%zu, first=%zu, second=%zu",
           write_len, first_len, second_len);
    
    spin_unlock_irqrestore(&priv->tx_splock, flags);

    /* 复制第一段（缓冲区尾部） */
    if (first_len && copy_from_user(&priv->tx_circ.msg[head], buf, 
        first_len * sizeof(struct canfd_msg_t))) {
        dev_err(priv->dev, "Failed to copy first segment: len=%zu", first_len);
        ret = -EFAULT;
        goto err_return;
    }
    /* 复制第二段（缓冲区头部回绕） */
    if (second_len && copy_from_user(&priv->tx_circ.msg[0], buf + first_len, 
        second_len * sizeof(struct canfd_msg_t))) {
        dev_err(priv->dev, "Failed to copy second segment: len=%zu", second_len);
        ret = -EFAULT;
        goto err_return;
    }

    dev_dbg(priv->dev, "Successfully copied data to buffer");

    /* 处理并发送数据 */
    for (i = 0; i < first_len; ) {
        // size_t idx = (tail + i) & (priv->tx_circ.size - 1);
        // xcan_msg_to_frame(priv->tx_circ.msg[idx], &priv->tx_frame);

        xcan_msg_to_frame(priv->tx_circ.msg[tail + i], &priv->tx_frame);
        if (wait_event_interruptible(priv->tx_wqh, circ_buf_empty(&priv->tx_circ))) {
            dev_err(priv->dev, "Circular write buffer wait interrupted.");
            return -ERESTARTSYS;
        }
        // spin_lock_irqsave(&priv->tx_splock, flags);
        // priv->tx_circ.head = (priv->tx_circ.head + 1) & (priv->tx_circ.size - 1);
        // spin_unlock_irqrestore(&priv->tx_splock, flags);
        /* 获取互斥锁 */
        if (mutex_lock_interruptible(&priv->lock)) {
            dev_dbg(priv->dev, "Write %s interrupted while waiting for mutex", priv->name);
            return -ERESTARTSYS;
        }
        if (xcan_start_xmit(&priv->tx_frame, priv) == 0) {
            dev_dbg(priv->dev, "Processed and sent frame from index %zu", tail + i);
            i++;
        }
        /* 释放互斥锁 */
        mutex_unlock(&priv->lock);
        dev_dbg(priv->dev, "Write done1, tx_circ.head=%lu tx_circ.tail=%lu", priv->tx_circ.head, priv->tx_circ.tail);
    }

    for (i = 0; i < second_len; ) {
        xcan_msg_to_frame(priv->tx_circ.msg[i], &priv->tx_frame);
        if (wait_event_interruptible(priv->tx_wqh, circ_buf_empty(&priv->tx_circ))) {
            dev_err(priv->dev, "Circular write buffer wait interrupted.");
            return -ERESTARTSYS;
        }
        // spin_lock_irqsave(&priv->tx_splock, flags);
        // priv->tx_circ.head = (priv->tx_circ.head + 1) & (priv->tx_circ.size - 1);
        // spin_unlock_irqrestore(&priv->tx_splock, flags);
        /* 获取互斥锁 */
        if (mutex_lock_interruptible(&priv->lock)) {
            dev_dbg(priv->dev, "Write %s interrupted while waiting for mutex", priv->name);
            return -ERESTARTSYS;
        }
        if (xcan_start_xmit(&priv->tx_frame, priv) == 0) {
            dev_dbg(priv->dev, "Processed and sent frame from index %u", i);
            i++;
        }
        /* 释放互斥锁 */
        mutex_unlock(&priv->lock);
        dev_dbg(priv->dev, "Write done2, tx_circ.head=%lu tx_circ.tail=%lu", priv->tx_circ.head, priv->tx_circ.tail);
    }

    // /* 更新缓冲区指针 */
    // spin_lock_irqsave(&priv->tx_splock, flags);
    // priv->tx_circ.head = (head + write_len) & (priv->tx_circ.size - 1);
    // priv->tx_circ.tail = (tail + write_len) & (priv->tx_circ.size - 1);
    // spin_unlock_irqrestore(&priv->tx_splock, flags);

    dev_dbg(priv->dev, "Wrote %zu frames to offset %lld", 
             write_len, *ppos);
    /* 更新文件位置和返回值 */
    // *ppos += write_len;
    ret = write_len;

    return ret;

err_return:

    return ret;
}

// IOCTL 处理
static long ioctl_xcan(struct file *filp, unsigned int cmd, 
                          unsigned long arg)
{
    struct xcan_dev_t *priv = filp->private_data;
    struct xcan_ctrl_t *pctrl = (struct xcan_ctrl_t *)priv->parent;
    struct reg_data_t reg_data;
    long ret = 0;
    u8 channel = 0;
    int mode = 0;
    
    if (!priv || !priv->dev) {
        return -ENODEV;
    }
    if (mutex_lock_interruptible(&priv->lock)) {    // 加锁
        return -ERESTARTSYS;
    }
    switch (cmd) {
    case IOCTL_XCAN_READ_REG:    // 读寄存器 指令
        if (copy_from_user(&reg_data, (void __user *)arg, sizeof(reg_data)))
            return -EFAULT;
        // 须应用层下发通道
        channel = ((reg_data.addr >> CANFD_DEV_ID_SHIFT) & 0xFF) % pctrl->num;
        reg_data.val = pctrl->xcan[channel].read_ipcore(&pctrl->xcan[channel], reg_data.addr);
        if (copy_to_user((void __user *)arg, &reg_data, sizeof(reg_data))) {
            ret = -EFAULT;
            break;
        }
        dev_info(pctrl->dev, "Read register 0x%x: 0x%x", 
                    reg_data.addr, reg_data.val);
        break;
    case IOCTL_XCAN_WRITE_REG:   // 写寄存器 指令
        if (copy_from_user(&reg_data, (void __user *)arg, sizeof(reg_data)))
            return -EFAULT;
        channel = ((reg_data.addr >> CANFD_DEV_ID_SHIFT) & 0xFF) % pctrl->num;
        pctrl->xcan[channel].write_ipcore(&pctrl->xcan[channel], reg_data.addr, reg_data.val);
        dev_info(pctrl->dev, "Write register 0x%x: 0x%x", 
                    reg_data.addr, reg_data.val);
        break;
    case IOCTL_XCAN_READ_MSG:    // 读取报文 指令
        break;
    case IOCTL_XCAN_CLEAR_MSG:   // 清空报文 指令
        for (channel = 0; channel < pctrl->num; channel++) {
            pctrl->xcan[channel].rx_circ.size = CIRC_BUF_SIZE;
            pctrl->xcan[channel].rx_circ.head = 0;
            pctrl->xcan[channel].rx_circ.tail = 0;
            memset(pctrl->xcan[channel].rx_circ.msg, 0, sizeof(pctrl->xcan[channel].rx_circ.msg));
        }
        break;
    case IOCTL_XCAN_SET_CTRLMODE:
        /* Set control mode */
        if (copy_from_user(&priv->can.ctrlmode, (void __user *)arg,
                           sizeof(priv->can.ctrlmode))) {
            ret = -EFAULT;
            goto unlock;
        }
        break;
    case IOCTL_XCAN_GET_CTRLMODE:
        /* Get control mode */
        if (copy_to_user((void __user *)arg, &priv->can.ctrlmode,
                         sizeof(priv->can.ctrlmode))) {
            ret = -EFAULT;
            goto unlock;
        }
        break;
    case IOCTL_XCAN_SET_BITTIMING:
        dev_dbg(priv->dev, "Set arbitration baud rate...");
        /* Set bit timing */
        if (copy_from_user(&priv->can.bittiming, (void __user *)arg,
                           sizeof(priv->can.bittiming))) {
            ret = -EFAULT;
            goto unlock;
        }
        if (priv->can.bittiming.sample_point == 0)
            priv->can.bittiming.sample_point = 800;     /* 80.0% */
        ret = xcan_calc_bittiming(&priv->can, &priv->can.bittiming, priv->can.bittiming_const);
        if (ret < 0) {
            dev_err(priv->dev, "Calculate bittiming.bitrate=%d failed", priv->can.bittiming.bitrate);
            goto unlock;
        }
        ret = set_reset_mode(priv);
        if (ret < 0) {
            goto unlock;
        }
        ret = xcan_set_bittiming(priv);
        if (ret < 0) {
            dev_err(priv->dev, "Set bittiming.bitrate=%d failed", priv->can.bittiming.bitrate);
            goto unlock;
        } else {
            dev_dbg(priv->dev, "Set bittiming.bitrate=%d success", priv->can.bittiming.bitrate);
        }
        break;
    case IOCTL_XCAN_GET_BITTIMING:
        /* Get bit timing */
        if (copy_to_user((void __user *)arg, &priv->can.bittiming,
                         sizeof(priv->can.bittiming))) {
            ret = -EFAULT;
            goto unlock;
        }
        break;
    case IOCTL_XCAN_SET_DATA_BITTIMING:
        dev_dbg(priv->dev, "Set data baud rate...");
        if (priv->devtype.cantype == XAXI_CANFD || 
            priv->devtype.cantype == XAXI_CANFD_2_0) {
            /* Set data bit timing (CAN FD) */
            if (copy_from_user(&priv->can.data_bittiming, (void __user *)arg,
                            sizeof(priv->can.data_bittiming))) {
                ret = -EFAULT;
                goto unlock;
            }
            if (priv->can.data_bittiming.sample_point == 0)
                priv->can.data_bittiming.sample_point = 800;    /* 80.0% */
            ret = xcan_calc_bittiming(&priv->can, &priv->can.data_bittiming, priv->can.data_bittiming_const);
            if (ret < 0) {
                dev_err(priv->dev, "Calculate data_bittiming.bitrate=%d failed", priv->can.data_bittiming.bitrate);
                goto unlock;
            }
            ret = set_reset_mode(priv);
            if (ret < 0) {
                goto unlock;
            }
            ret = xcan_set_bittiming(priv);
            if (ret < 0) {
                dev_err(priv->dev, "Set data_bittiming.bitrate=%d failed", priv->can.data_bittiming.bitrate);
                goto unlock;
            } else {
                dev_dbg(priv->dev, "Set data_bittiming.bitrate=%d success", priv->can.data_bittiming.bitrate);
            }
        }
        break;
    case IOCTL_XCAN_GET_DATA_BITTIMING:
        /* Get data bit timing (CAN FD) */
        if (copy_to_user((void __user *)arg, &priv->can.data_bittiming,
                         sizeof(priv->can.data_bittiming))) {
            ret = -EFAULT;
            goto unlock;
        }
        break;
    case IOCTL_XCAN_SET_FILTER:
        if (copy_from_user(&priv->filter, (void __user *)arg,
                           sizeof(priv->filter))) {
            ret = -EFAULT;
            goto unlock;
        }
        if (priv->devtype.cantype == XAXI_CANFD || 
            priv->devtype.cantype == XAXI_CANFD_2_0) {
            if (priv->devtype.flags & XCAN_FLAG_EXT_FILTERS)
                priv->write_ipcore(priv, XCAN_AFR_EXT_OFFSET, 0x00000000);
            if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
                priv->write_ipcore(priv, XCAN_AFR_2_MASK_OFFSET, priv->filter.mask);
                priv->write_ipcore(priv, XCAN_AFR_2_ID_OFFSET, priv->filter.id);
            }
            if (priv->devtype.flags & XCAN_FLAG_EXT_FILTERS)
                priv->write_ipcore(priv, XCAN_AFR_EXT_OFFSET, 0x00000001);
        } else {
            priv->write_ipcore(priv, XCAN_AFR_OFFSET, 0x00000000);
            priv->write_ipcore(priv, XCAN_AFMR_1_OFFSET, priv->filter.mask);
            priv->write_ipcore(priv, XCAN_AFIR_1_OFFSET, priv->filter.id);
            priv->write_ipcore(priv, XCAN_AFR_OFFSET, 0x00000001);
        }
        break;
    case IOCTL_XCAN_SET_MODE:
        if (copy_from_user(&mode, (void __user *)arg, sizeof(mode))) {
            ret = -EFAULT;
            goto unlock;
        }
        switch (mode) {
        case CAN_MODE_START:
            ret = xcan_chip_start(priv);
            if (ret < 0) {
                dev_err(priv->dev, "xcan_chip_start failed");
                goto unlock;
            }
            break;
        default:
            ret = -EOPNOTSUPP;
            goto unlock;
        }
        break;
    /* 获取状态 */
    case IOCTL_XCAN_GET_STA:
        get_xcan_sta(priv);
        if (copy_to_user((void __user *)arg, &priv->sta, sizeof(priv->sta))) {
            dev_err(priv->dev, "Get %s SR copy failed", priv->name);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取错误计数 */
    case IOCTL_XCAN_GET_ERR_CNT:
        get_xcan_ecnt(priv);
        if (copy_to_user((void __user *)arg, &priv->ecnt, sizeof(priv->ecnt))) {
            dev_err(priv->dev, "Get %s ECR copy failed", priv->name);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取驱动版本号 */
    case IOCTL_XCAN_GET_DRV_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->drv_ver, sizeof(pctrl->drv_ver))) {
            dev_err(pctrl->dev, "Get %s driver version %d copy failed", pctrl->name, pctrl->drv_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 FPGA 版本号 */
    case IOCTL_XCAN_GET_FPGA_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->fpga_ver, sizeof(pctrl->fpga_ver))) {
            dev_err(pctrl->dev, "Get %s FPGA version %d copy failed", pctrl->name, pctrl->fpga_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    default:
        dev_err(priv->dev, "Ioctl %s cmd=0x%08x, dir=0x%X, size=%u, type=0x%02X('%c'), nr=%u not support\n",
                priv->name, cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd), _IOC_TYPE(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd));
        ret = -ENOTTY;
        goto unlock;
        break;
    }

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

/**
 * xcan_tx_interrupt - Tx Done Isr
 * @ndev:	net_device pointer
 * @isr:	Interrupt status register value
 */
static void xcan_tx_interrupt(struct xcan_dev_t *priv, u32 isr)
{
	// struct xcan_dev_t *priv = netdev_priv(ndev);
	// struct xcan_device_stats *stats = &priv->stats;
	unsigned int frames_in_fifo;
	int frames_sent = 1; /* TXOK => at least 1 frame was sent */
	unsigned long flags;
	int retries = 0;

	/* Synchronize with xmit as we need to know the exact number
	 * of frames in the FIFO to stay in sync due to the TXFEMP
	 * handling.
	 * This also prevents a race between netif_wake_queue() and
	 * netif_stop_queue().
	 */
	spin_lock_irqsave(&priv->tx_lock, flags);

	// frames_in_fifo = priv->tx_head - priv->tx_tail;
    frames_in_fifo = (priv->tx_circ.head - priv->tx_circ.tail) & (priv->tx_circ.size - 1);

	if (WARN_ON_ONCE(frames_in_fifo == 0)) {
		/* clear TXOK anyway to avoid getting back here */
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
        dev_dbg(priv->dev, "TX interrupt with no frames in FIFO");
		spin_unlock_irqrestore(&priv->tx_lock, flags);
		return;
	}

    dev_dbg(priv->dev, "TX interrupt, frames in FIFO: %u, ISR: 0x%08x head=%lu tail=%lu",
            frames_in_fifo, isr, priv->tx_circ.head, priv->tx_circ.tail);

	/* Check if 2 frames were sent (TXOK only means that at least 1
	 * frame was sent).
	 */
	if (frames_in_fifo > 1) {
		WARN_ON(frames_in_fifo > priv->tx_max);

		/* Synchronize TXOK and isr so that after the loop:
		 * (1) isr variable is up-to-date at least up to TXOK clear
		 *     time. This avoids us clearing a TXOK of a second frame
		 *     but not noticing that the FIFO is now empty and thus
		 *     marking only a single frame as sent.
		 * (2) No TXOK is left. Having one could mean leaving a
		 *     stray TXOK as we might process the associated frame
		 *     via TXFEMP handling as we read TXFEMP *after* TXOK
		 *     clear to satisfy (1).
		 */
		while ((isr & XCAN_IXR_TXOK_MASK) &&
		       !WARN_ON(++retries == 100)) {
			priv->write_ipcore(priv, XCAN_ICR_OFFSET,
					XCAN_IXR_TXOK_MASK);
			isr = priv->read_ipcore(priv, XCAN_ISR_OFFSET);
		}

        if (retries >= 100) {
            dev_err(priv->dev, "Failed to clear TXOK after 100 retries");
        }

		if (isr & XCAN_IXR_TXFEMP_MASK) {
			/* nothing in FIFO anymore */
			frames_sent = frames_in_fifo;
            dev_dbg(priv->dev, "TX FIFO empty, all %u frames sent",
                    frames_sent);
		}
	} else {
		/* single frame in fifo, just clear TXOK */
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
        dev_dbg(priv->dev, "Single frame sent, cleared TXOK");
	}

	while (frames_sent--) {
		// stats->tx_bytes += can_get_echo_skb(ndev, priv->tx_tail %
		// 				    priv->tx_max);
		// priv->tx_tail++;
		// stats->tx_packets++;
        priv->tx_circ.tail = (priv->tx_circ.tail + 1) & (priv->tx_circ.size - 1);
        dev_dbg(priv->dev, "Processed TX frame, new tail: %lu",
                priv->tx_circ.tail);
	}

	// netif_wake_queue(ndev);
    wake_up_interruptible(&priv->tx_wqh);
    dev_dbg(priv->dev, "Wake up tx queue");

	spin_unlock_irqrestore(&priv->tx_lock, flags);

	// can_led_event(ndev, CAN_LED_EVENT_TX);
	xcan_update_error_state_after_rxtx(priv);
    dev_dbg(priv->dev, "TX interrupt processing completed");
}

/* CAN device restart for bus-off recovery */
void xcan_restart(struct xcan_dev_t *pdev)
{
	// struct can_priv *pdev = netdev_priv(dev);
	struct xcan_device_stats *stats = &pdev->stats;
	// struct sk_buff *skb;
	struct can_frame *cf = (struct can_frame *)&pdev->rx_frame;
	int err;

	// if (netif_carrier_ok(dev))
		dev_err(pdev->dev, "Attempt to restart for bus-off recovery, but carrier is OK?");

	/* No synchronization needed because the device is bus-off and
	 * no messages can come in or go out.
	 */
	// can_flush_echo_skb(dev);

	/* send restart message upstream */
	// skb = alloc_can_err_skb(dev, &cf);
    /* alloc_can_err_skb 中有如下赋值 */
    cf->can_id = CAN_ERR_FLAG;
    cf->can_dlc = CAN_ERR_DLC;

	if (!cf)
		goto restart;

	cf->can_id |= CAN_ERR_RESTARTED;

	stats->rx_packets++;
	stats->rx_bytes += cf->can_dlc;

#ifdef XCAN_BERR_REPORT
	// netif_rx_ni(skb);
    unsigned long flags;
    /* 环形缓冲区操作 */
    spin_lock_irqsave(&pdev->rx_splock, flags);
    xcan_frame_to_msg(*(struct canfd_frame *)&cf, &pdev->rx_circ.msg[pdev->rx_circ.head]);
    if (circ_buf_full(&pdev->rx_circ)) {
        /* 丢弃最旧数据，位运算 & 比取模运算 % 快 10 倍以上（CPU 指令周期更少） */
        // pdev->rx_circ.tail = (pdev->rx_circ.tail + 1) % pdev->rx_circ.size;
        pdev->rx_circ.tail = (pdev->rx_circ.tail + 1) & (pdev->rx_circ.size - 1);
    }
    pdev->rx_circ.head = (pdev->rx_circ.head + 1) & (pdev->rx_circ.size - 1);
    spin_unlock_irqrestore(&pdev->rx_splock, flags);
    wake_up_interruptible(&pdev->rx_wqh);
#endif /* XCAN_BERR_REPORT */

restart:
	dev_info(pdev->dev, "restarted");
	pdev->can.can_stats.restarts++;

	/* Now restart the device */
	// netif_carrier_on(dev);
	err = xcan_do_set_mode(pdev, CAN_MODE_START);
	if (err) {
		dev_err(pdev->dev, "Error %d during restart", err);
		// netif_carrier_off(dev);
	}
}

void xcan_restart_work(struct work_struct *work)
{
	struct delayed_work *dwork = to_delayed_work(work);
    struct can_priv *can = container_of(dwork, struct can_priv, restart_work);
	struct xcan_dev_t *priv = container_of(can, struct xcan_dev_t, can);

	xcan_restart(priv);
}

/**
 * xcan_interrupt - CAN Isr
 * @irq_ctrl:	irq_ctrl number
 * @dev_id:	device id pointer
 *
 * This is the xilinx CAN Isr. It checks for the type of interrupt
 * and invokes the corresponding ISR.
 *
 * Return:
 * IRQ_NONE - If CAN device is in sleep mode, IRQ_HANDLED otherwise
 */
static irqreturn_t xcan_interrupt(int irq, void *dev_id)
{
	struct xcan_dev_t *priv = (struct xcan_dev_t *)dev_id;
	u32 isr, ier;
	u32 isr_errors;
	u32 rx_int_mask = xcan_rx_int_mask(priv);

	/* 打印进入中断的基本信息 */
	dev_dbg(priv->dev, "IRQ: %s irq=%d", priv->name, irq);

	/* Get the interrupt status from Xilinx CAN */
	isr = priv->read_ipcore(priv, XCAN_ISR_OFFSET);
	dev_dbg(priv->dev, "ISR=0x%08x", isr);
	
	if (!isr) {
		dev_dbg(priv->dev, "No interrupt status found, returning IRQ_NONE");
		return IRQ_NONE;
	}

	/* Check for the type of interrupt and Processing it */
	if (isr & (XCAN_IXR_SLP_MASK | XCAN_IXR_WKUP_MASK)) {
		dev_warn(priv->dev, "Sleep/Wakeup interrupt detected (ISR=0x%08x)", isr);
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, (XCAN_IXR_SLP_MASK |
				XCAN_IXR_WKUP_MASK));
		xcan_state_interrupt(priv, isr);
	}

	/* Check for Tx interrupt and Processing it */
	if (isr & XCAN_IXR_TXOK_MASK) {
		dev_dbg(priv->dev, "Transmit interrupt detected (ISR=0x%08x)", isr);
		xcan_tx_interrupt(priv, isr);
	}

	/* Check for the type of error interrupt and Processing it */
	isr_errors = isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
			    XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK |
			    XCAN_IXR_RXMNF_MASK);
	if (isr_errors) {
		dev_warn(priv->dev, "Error interrupt detected (ISR=0x%08x, errors=0x%08x)",
			 isr, isr_errors);
		priv->write_ipcore(priv, XCAN_ICR_OFFSET, isr_errors);
		xcan_err_interrupt(priv, isr);
	}

	/* Check for the type of receive interrupt and Processing it */
	if (isr & rx_int_mask) {
		dev_dbg(priv->dev, "Receive interrupt detected (ISR=0x%08x)", isr);
		ier = priv->read_ipcore(priv, XCAN_IER_OFFSET);
		dev_dbg(priv->dev, "Original IER=0x%08x", ier);
		ier &= ~rx_int_mask;
		dev_dbg(priv->dev, "Modified IER=0x%08x (masked with 0x%08x)", 
			 ier, ~rx_int_mask);
		priv->write_ipcore(priv, XCAN_IER_OFFSET, ier);
		schedule_work(&priv->work);
	}

	dev_dbg(priv->dev, "Interrupt processing completed");
	return IRQ_HANDLED;
}

// 工作队列处理函数(中断下半部)
static void work_queue_handler(struct work_struct *work)
{
    struct xcan_dev_t *priv = container_of(work, struct xcan_dev_t, work);
    int quota = XCAN_RX_FIFO_DEPTH;
    u32 ier = 0;
    int work_done = 0;
    int frame_offset = 0;

	while ((frame_offset = xcan_rx_fifo_get_next_frame(priv)) >= 0 &&
	       (work_done < quota)) {
		if (xcan_rx_int_mask(priv) & XCAN_IXR_RXOK_MASK)
			work_done += xcanfd_rx(priv, frame_offset);
		else
			work_done += xcan_rx(priv, frame_offset);

		if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI)
			/* increment read index */
			priv->write_ipcore(priv, XCAN_FSR_OFFSET,
					XCAN_FSR_IRI_MASK);
		else
			/* clear rx-not-empty (will actually clear only if
			 * empty)
			 */
			priv->write_ipcore(priv, XCAN_ICR_OFFSET,
					XCAN_IXR_RXNEMP_MASK);
	}

	if (work_done) {
		// can_led_event(ndev, CAN_LED_EVENT_RX);
		xcan_update_error_state_after_rxtx(priv);
	}

	if (work_done < quota) {
		// if (napi_complete_done(napi, work_done)) {
			ier = priv->read_ipcore(priv, XCAN_IER_OFFSET);
			ier |= xcan_rx_int_mask(priv);
			priv->write_ipcore(priv, XCAN_IER_OFFSET, ier);
		// }
	}
	// return work_done;

    // 这里执行需要在进程上下文中处理的任务
    dev_dbg(priv->dev, "%s interrupt handled", priv->name);
    // 注意：在这个函数中，可以安全地调用可能睡眠的函数
}

static int init_canfd(void *parent, struct xcan_dev_t *priv, const struct xcan_devtype_data *devtype, 
                      void __iomem *reg_base, u8 index)
{
    struct xcan_ctrl_t *pctrl = (struct xcan_ctrl_t *)parent;
    int ret = 0;
    const struct xcan_devtype_data *xcan_devtype = devtype;

    priv->parent = (struct xcan_ctrl_t *)parent;
    priv->dev = pctrl->dev;
    priv->can.bittiming_const = xcan_devtype->bittiming_const;
    // priv->can.do_set_mode = xcan_do_set_mode;
    // priv->can.do_get_berr_counter = xcan_get_berr_counter;
    priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
                    CAN_CTRLMODE_BERR_REPORTING;
    if (xcan_devtype->cantype == XAXI_CANFD_2_0)
        priv->can.data_bittiming_const =
            &xcan_data_bittiming_const_canfd2;
    if (xcan_devtype->cantype == XAXI_CANFD ||
        xcan_devtype->cantype == XAXI_CANFD_2_0)
        priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
    priv->reg_base = reg_base;
    priv->devtype = *xcan_devtype;
    priv->index = index;
    snprintf(priv->name, sizeof(priv->name), "%s%d", pctrl->name, index);

    priv->read_ipcore = xcan_read_reg_le;
    priv->write_ipcore = xcan_write_reg_le;
    if (priv->devtype.cantype == XAXI_CANFD_2_0) {
        priv->wr_addr_reg = CANFD_WR_ADDR_REG;
        priv->wr_data_reg = CANFD_WR_DATA_REG;
        priv->rd_addr_reg = CANFD_RD_ADDR_REG;
        priv->rd_data_reg = CANFD_RD_DATA_REG;
        priv->can.clock.freq = 40000000;
    } else if (priv->devtype.cantype == XAXI_CAN) {
        priv->wr_addr_reg = CAN_WR_ADDR_REG;
        priv->wr_data_reg = CAN_WR_DATA_REG;
        priv->rd_addr_reg = CAN_RD_ADDR_REG;
        priv->rd_data_reg = CAN_RD_DATA_REG;
        priv->can.clock.freq = 24000000;

        priv->tx_max = 1;
    }

    /* 初始化互斥锁 */
    mutex_init(&priv->lock);

    spin_lock_init(&priv->rx_splock);
    init_waitqueue_head(&priv->rx_wqh);

    spin_lock_init(&priv->tx_lock);
    init_waitqueue_head(&priv->tx_wqh);

    /* 初始化环形缓冲区 */
    priv->rx_circ.size = CIRC_BUF_SIZE;
    priv->rx_circ.head = 0;
    priv->rx_circ.tail = 0;
    memset(priv->rx_circ.msg, 0, sizeof(priv->rx_circ.msg));
    priv->tx_circ.size = CIRC_BUF_SIZE;
    priv->tx_circ.head = 0;
    priv->tx_circ.tail = 0;
    memset(priv->tx_circ.msg, 0, sizeof(priv->tx_circ.msg));

    priv->can.restart_ms = 100;
    INIT_DELAYED_WORK(&priv->can.restart_work, xcan_restart_work);

    // 初始化工作队列
    INIT_WORK(&priv->work, work_queue_handler);

    dev_dbg(priv->dev, "Init %s success", priv->name);

    return ret;
}

/* 初始化 XCAN 控制器 */
int init_xcan_ctrl(struct pcie_dev_t *ppdev, struct cdev_dev_t *cdev_dev, 
                   struct xcan_ctrl_t *pctrl, struct xcan_dev_t *xcan, 
                   const char *ctrl_name, u8 dev_num, const struct xcan_devtype_data *type)
{
    int ret = 0;
    u8 i = 0;
    char name[32];

    pctrl->dev = &ppdev->pdev->dev;
    /* 初始化互斥锁 */
    mutex_init(&pctrl->lock);
    snprintf(pctrl->name, sizeof(pctrl->name), "%s", ctrl_name);
    pctrl->num = dev_num;
    pctrl->ppdev = ppdev;
    pctrl->read_reg = read_xcan_reg_le;
    pctrl->write_reg = write_xcan_reg_le;
    pctrl->read_mem = read_xcan_mem_le;
    pctrl->write_mem = write_xcan_mem_le;
    pctrl->cdev_ctrl.cdev_dev = cdev_dev;
    pctrl->xcan = xcan;
    if (type->cantype == XAXI_CANFD || 
        type->cantype == XAXI_CANFD_2_0) {
        pctrl->drv_ver = CDEV_DRV_VERSION(CANFD_VER_MAJOR, CANFD_VER_MINOR, CANFD_VER_PATCH);
        pctrl->fpga_ver = pctrl->read_mem(ppdev->bar[0], XCAN_VERSION_OFFSET);
    } else {
        pctrl->drv_ver = CDEV_DRV_VERSION(CAN_VER_MAJOR, CAN_VER_MINOR, CAN_VER_PATCH);
        pctrl->fpga_ver = pctrl->read_mem(ppdev->bar[0], XCAN_VERSION_OFFSET);
    }

    dev_dbg(pctrl->dev, "Init %s pcie interrupt...", pctrl->name);
    /* 初始化中断 */
    disable_msi_irq(pctrl);
    enable_msi_irq(pctrl);
    if (type->cantype == XAXI_CANFD || 
        type->cantype == XAXI_CANFD_2_0) {
        pctrl->irq_ctrl.irq = &pcie_irq;
        ret = init_pcie_irq(pctrl->ppdev->pdev, &pctrl->irq_ctrl, 
                            PCI_IRQ_MSI, XCANFD_MSI_VEC_START, (XCANFD_MSI_VEC_START + dev_num - 1), 
                            xcan_interrupt, pctrl->name,
                            pctrl->xcan, sizeof(struct xcan_dev_t), pctrl->ppdev->bar[0]);
        if (ret) {
            dev_err(pctrl->dev, "Init %s pcie interrupt failed", pctrl->name);
            goto err_free_dev;
        }
    } else if (type->cantype == XAXI_CAN) {
        pctrl->irq_ctrl.irq = &pcie_irq;
        ret = init_pcie_irq(pctrl->ppdev->pdev, &pctrl->irq_ctrl, 
                            PCI_IRQ_MSI, XCAN_MSI_VEC_START, (XCAN_MSI_VEC_START + dev_num - 1), 
                            xcan_interrupt, pctrl->name,
                            pctrl->xcan, sizeof(struct xcan_dev_t), pctrl->ppdev->bar[0]);
        if (ret) {
            dev_err(pctrl->dev, "Init %s pcie interrupt failed", pctrl->name);
            goto err_free_dev;
        }
    }

    dev_dbg(pctrl->dev, "Init %s cdev controller...", pctrl->name);
    /* 初始化字符设备 */
    ret = init_cdev_ctrl(pctrl, &pctrl->cdev_ctrl, pctrl->name, dev_num);
    if (ret < 0) {
        dev_err(pctrl->dev, "Init %s controller failed", pctrl->name);
        goto err_cleanup_irq;
    }
    dev_dbg(pctrl->dev, "Init %s cdev device...", pctrl->name);
    for (i = 0; i < dev_num; i++) {
        snprintf(name, sizeof(name), "%s%d", pctrl->name, i);
        ret = init_cdev_dev(&pctrl->cdev_ctrl, pctrl->cdev_ctrl.cclass, 
                            &pctrl->cdev_ctrl.cdev_dev[i], &cdev_fops, pctrl->cdev_ctrl.major_devno, name, i);
        if (ret) {
            dev_err(pctrl->dev, "Init %s device failed", name);
            goto err_class_destroy;
        }
    }

    dev_dbg(pctrl->dev, "Init %s device...", pctrl->name);
    for (i = 0; i < dev_num; i++) {
        init_canfd(pctrl, &pctrl->xcan[i], type, pctrl->ppdev->bar[0], i);       // 初始化 CANFD
    }

    return 0;

// 错误处理路径
err_class_destroy:
    // class_destroy(pctrl->cclass);
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
err_cleanup_irq:
    exit_pcie_irq(&pctrl->irq_ctrl, pctrl->xcan, sizeof(struct xcan_dev_t));
err_free_dev:
    // devm 会自动释放内存

    return ret;
}

/* 注销 XCAN 控制器 */
void exit_xcan_ctrl(struct xcan_ctrl_t *pctrl, u8 dev_num)
{
    u8 i = 0;

    if (!pctrl) {
        pr_err("Invalid parameters for %s", __FUNCTION__);
        return;
    }

    for (i = 0; i < dev_num; i++) {
        exit_cdev_dev(pctrl->cdev_ctrl.cclass, &pctrl->cdev_ctrl.cdev_dev[i]);
    }
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
    dev_info(pctrl->dev, "class_destroy done");

    exit_pcie_irq(&pctrl->irq_ctrl, pctrl->xcan, sizeof(struct xcan_dev_t));
    dev_info(pctrl->dev, "exit_pcie_irq done");

    // mutex_destroy(&pctrl->lock);
    dev_info(pctrl->dev, "PCIe character device %s removed", pctrl->name);
}
